﻿using System;
using System.IO;
using System.Xml;
using System.Xml.Schema;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace Nizm0.QOT.Library.Objects
{
    [Serializable]
    public sealed class ProjectSettings : Project, IXmlSerializable //: System.Collections.IList
    {
        private static volatile ProjectSettings instance;// = new ProjectSettings()
        private static object syncRoot = new Object();

        /// <summary>
        /// Settings from curent project
        /// </summary>
        public static ProjectSettings Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (syncRoot)
                    {
                        if (instance == null)
                        {
                            instance = new ProjectSettings();
                            Settings.Instance.ProjectSettings = instance;
                        }
                    }
                }
                return instance;
            }
        }

        /// <summary>
        /// level on the tree {server = 0, database = 1, folder = 2, table = 3, procedure = 3}
        /// </summary>
        public enum ObjectLevelOnTree { Server = 0, Database = 1, Folder = 2, Table = 3, Procedure = 3 }

        public string FileTypeName { get { return "QOT files"; } }
        private string _fileExtension = ".qot";
        [XmlIgnore()]
        public string FileExtension
        {
            get { return _fileExtension; }
            private set { _fileExtension = value; }
        }

        public static int Count = 0;
        private int _queries;
        //private bool _isSecondServer;

        private bool _saved = true;
        private bool _isLoaded = false;
        private int _runnigProcesses = 0;

        private bool _forceStop;

        private LocalStorage.LocalStorage _localStorage = new LocalStorage.LocalStorage(true);

        public LocalStorage.LocalStorage LocalStorage
        {
            get { return _localStorage; }
        }

        private DateTime _datestart;
        private DateTime _datestop;

        private int _diferentsForDates;

        private List<FileSystemWatcher> _listOfFileWatcher = new List<FileSystemWatcher>();
        private bool _searchFolderImmediately = true;

        //[NonSerialized]
        //private Dictionary<string, ProcedureInfo> _procedures = new Dictionary<string, ProcedureInfo>();
        private List<IProcedureInfo> _procedureList = new List<IProcedureInfo>();

        private Queue<Library.Objects.IProcedureInfo> _queue = new Queue<Library.Objects.IProcedureInfo>();

        private ArrayList _filterList = new ArrayList();
        [NonSerialized]
        private List<Server> _servers = new List<Server>();

        [NonSerialized]
        private Dictionary<string, DateTime> _filesChanged = new Dictionary<string, DateTime>();

        #region Delegates


        //public delegate void DelegateAddNewProcedure(Library.Objects.ProcedureInfo procedure, bool Looking);
        public event DelegateAddNewProcedure NewEventAddNewProcedure;
        public event DelegateDeleteProcedure NewEventDeleteProcedure;

        //public delegate void OnServerChange(Object sender);
        public event OnServerChange ServerChange;

        //public delegate void OnSaveStatusChange(Boolean saveStatus);
        public event OnSaveStatusChange SaveStatusChanche;

        //public new delegate void ChangeStatusEvetHendler(String str);
        public new event ChangeStatusEvetHendler StatusChange;

        //public new delegate void OnErrorEventHandler(object obj, Exception ex);
        public new event ErrorEventHandler ErrorEvent;

        public event Library.OpenFormEventHandler OpenProcedure;

        private void ProjectSettings_ObservedDirectoryDeleted(string Directory)
        {
            RemoveFileWather(Directory);
            //throw new NotImplementedException();
        }

        private void ProjectSettings_ObservedDirectoryAdded(string Directory)
        {
            //throw new NotImplementedException();
            AddSetFileWatcher(Directory);
        }

        private void ProjectSettings_ObservedDirectoryChange(string DirectoryOld, string DirectoryNew)
        {

        }
        #endregion

        #region Parameters
        /// <summary>
        /// Get server list specified by the user
        /// </summary>
        public List<Server> Servers
        {
            get { return _servers; }
            //set
            //{
            //    _servers = value;
            //    if (ServerChange != null)
            //        ServerChange(value);
            //}
        }
        /// <summary>
        /// Get or Set max numbers of results to print
        /// </summary>
        public int Queries
        {
            get { return _queries; }
            set { _queries = value; }
        }
        //public bool IsSecontServer
        //{
        //    get { return _isSecondServer; }
        //    set { _isSecondServer = value; }
        //}
        /// <summary>
        /// Get falue if settings are saved
        /// </summary>
        public bool Saved
        {
            get { return _saved; }
            //set
            //{
            //    _saved = value;
            //    if (SaveStatusChanche != null) SaveStatusChanche(value);
            //}
        }
        /// <summary>
        /// Get falue if settings are loaded
        /// </summary>
        public bool IsLoaded
        {
            get { return _isLoaded; }
            //set { _isLoaded = value; }
        }
        /// <summary>
        /// Get or Set if is alowed to force stop process
        /// </summary>
        public bool ForceStop
        {
            get { return _forceStop; }
            set { _forceStop = value; }
        }
        /// <summary>
        /// Get or Set the date from which the data will be searched in the process
        /// </summary>
        public DateTime DateStart
        {
            get { return _datestart; }
            set { _datestart = value; }
        }
        /// <summary>
        /// Get or Set the date to which the data will be searched in the process
        /// </summary>
        public DateTime DateStop
        {
            get { return _datestop; }
            set { _datestop = value; }
        }
        /// <summary>
        /// Get or Set the tiferents betwean DateStart and DateStop in month
        /// </summary>
        public int DiferentsForDates
        {
            get { return _diferentsForDates; }
            set { _diferentsForDates = value; }
        }
        //public Dictionary<string, ProcedureInfo> Procedures
        //{
        //    get { return _procedures; }
        //    set { _procedures = value; }
        //}
        [XmlIgnore()]
        public List<IProcedureInfo> ProceduresList
        {
            get { return _procedureList; }
            set { _procedureList = value; }
        }
        //public server ProfilerServer
        //{
        //    get { return _profilerServer; }
        //    set { _profilerServer = value; }
        //}

        //public server TestServer
        //{
        //    get { return _testServer; }
        //    set { _testServer = value; }
        //}
        public ArrayList FilterList
        {
            get { return _filterList; }
            set { _filterList = value; }
        }
        /// <summary>
        /// Get list File Watchers
        /// </summary>
        [XmlIgnore()]
        public List<FileSystemWatcher> ListOfFileWatcher
        {
            get { return _listOfFileWatcher; }
            //set { _listOfFileWatcher = value; }
        }
        #endregion

        #region Constructors

        private ProjectSettings()
        {
            ProcedureInfo.SetNewVersionAddEvent(procedure_OnNewVersionAdd);
            ProcedureInfo.SetVersionChangeEvent(procedure_OnVersionChange);
            ProcedureInfo.SetProcedureUpdateEvent(procedure_OnProcedureUpdate);
            NewEventAddNewProcedure += new DelegateAddNewProcedure(ProjectSettings_NewEventAddNewProcedure);
        }

        ~ProjectSettings()
        {
            Count--;
            //Debug.WriteLine(Count, "Ilość obiektów AllSetings");

            //MessageBox.Show("Zwalnianie Ustawień");
        }
        #endregion

        #region Methods

        public bool Load()
        //: base(project)
        {
            return Load(base.FileName);
            ////base.ProjectNewProcedureLocationChange += new ProcedureLocationChangeEventHandler(ProjectSettings_ProjectNewProcedureLocationChange);
            ////base.ProjectOldProcedureLocationChange += new ProcedureLocationChangeEventHandler(ProjectSettings_ProjectOldProcedureLocationChange);
            //base.ObservedDirectoryAdded += new ProcedureLocationChangeEventHandler(ProjectSettings_ObservedDirectoryAdded);
            //base.ObservedDirectoryDeleted += new ProcedureLocationChangeEventHandler(ProjectSettings_ObservedDirectoryDeleted);

            ////Count++;
            //_queries = 100;
            ////Debug.WriteLine(Count, "Ilość obiektów AllSetings");
            ////base.FileName;
            ////this._filename = "Standard.qot";
            ////base.ProjectOldProcedureLocation = project.ProjectOldProcedureLocation;
            ////base.ProjectNewProcedureLocation = project.ProjectNewProcedureLocation;

            //AddObservedDirectories(base.ProjectOldProcedureLocation);
            //AddObservedDirectories(base.ProjectNewProcedureLocation);

            //if (!LoadSettings(base.FileName)) return false;

            ////project.StatusChange += new Library.Objects.Project.ChangeStatusEvetHendler(StatusChange);
            ////if(!string.IsNullOrWhiteSpace(base.ProjectOldProcedureLocation))
            ////    SetFileWatcher(base.ProjectOldProcedureLocation);
            ////if (!string.IsNullOrWhiteSpace(base.ProjectNewProcedureLocation))
            ////    SetFileWatcher(base.ProjectNewProcedureLocation);
            //_isLoaded = true;
            //return true;
        }

        public void Load(int ID, string ServerAdress, bool SSPI, string Login, string Password, List<DataBase> DataBase, Project project)
        //: base(project)
        {
            //base.ProjectNewProcedureLocationChange += new ProcedureLocationChangeEventHandler(ProjectSettings_ProjectNewProcedureLocationChange);
            //base.ProjectOldProcedureLocationChange += new ProcedureLocationChangeEventHandler(ProjectSettings_ProjectOldProcedureLocationChange);
            base.ObservedDirectoryAdded += new ObservedDirectoryChangeEventHandler(ProjectSettings_ObservedDirectoryAdded);
            base.ObservedDirectoryDeleted += new ObservedDirectoryChangeEventHandler(ProjectSettings_ObservedDirectoryDeleted);

            //Count++;
            _queries = 100;
            //Debug.WriteLine(Count, "Ilość obiektów AllSetings");

            //this._filename = FileName;
            //ProfilerServer a = new ProfilerServer(ID, ServerAdress, SSPI, login, Password, Queries, database);
            _servers.Add(new Library.Objects.Server(ID, ServerAdress, SSPI, Login, Password, DataBase));

            //SetFileWatcherOLD(base.ProjectOldProcedureLocation);
            //SetFileWatcherNEW(base.ProjectNewProcedureLocation);
            //_proceduresList.AddRange(_procedures.Values);
            _isLoaded = true;
        }

        public bool Load(string FileName)
        {
            //base.ProjectNewProcedureLocationChange += new ProcedureLocationChangeEventHandler(ProjectSettings_ProjectNewProcedureLocationChange);
            //base.ProjectOldProcedureLocationChange += new ProcedureLocationChangeEventHandler(ProjectSettings_ProjectOldProcedureLocationChange);
            base.ObservedDirectoryAdded += new ObservedDirectoryChangeEventHandler(ProjectSettings_ObservedDirectoryAdded);
            base.ObservedDirectoryDeleted += new ObservedDirectoryChangeEventHandler(ProjectSettings_ObservedDirectoryDeleted);
            base.ObservedDirectoryChange += new ObservedDirectoryChangeDirectoryEventHandler(ProjectSettings_ObservedDirectoryChange);

            //Count++;
            _queries = 100;
            //Debug.WriteLine(Count, "Ilość obiektów AllSetings");
            //base.FileName = FileName;
            if (!LoadSettings(FileName)) return false;
            base.FileName = FileName;

            //SetFileWatcherOLD(base.ProjectOldProcedureLocation);
            //SetFileWatcherNEW(base.ProjectNewProcedureLocation);
            _isLoaded = true;
            return true;
        }

        public bool Load(Project project)
        //: base(project)
        {
            //base.ProjectNewProcedureLocationChange += new ProcedureLocationChangeEventHandler(ProjectSettings_ProjectNewProcedureLocationChange);
            //base.ProjectOldProcedureLocationChange += new ProcedureLocationChangeEventHandler(ProjectSettings_ProjectOldProcedureLocationChange);
            base.ObservedDirectoryAdded += new ObservedDirectoryChangeEventHandler(ProjectSettings_ObservedDirectoryAdded);
            base.ObservedDirectoryDeleted += new ObservedDirectoryChangeEventHandler(ProjectSettings_ObservedDirectoryDeleted);

            //Count++;
            _queries = 100;
            //Debug.WriteLine(Count, "Ilość obiektów AllSetings");
            //base.FileName;
            //this._filename = "Standard.qot";
            //base.ProjectOldProcedureLocation = project.ProjectOldProcedureLocation;
            //base.ProjectNewProcedureLocation = project.ProjectNewProcedureLocation;

            if (!LoadSettings(project.FileName)) return false;
            project.FileName = this.FileName;

            //project.StatusChange += new Library.Objects.Project.ChangeStatusEvetHendler(StatusChange);
            //if(!string.IsNullOrWhiteSpace(base.ProjectOldProcedureLocation))
            //    SetFileWatcher(base.ProjectOldProcedureLocation);
            //if (!string.IsNullOrWhiteSpace(base.ProjectNewProcedureLocation))
            //    SetFileWatcher(base.ProjectNewProcedureLocation);
            _isLoaded = true;
            return true;
        }

        public void Unload()
        {
            _listOfFileWatcher.Clear();
            //_procedures.Clear();
            _procedureList.Clear();
            _filesChanged.Clear();

            _servers.Clear();
            _isLoaded = false;
        }

        public bool LoadSettings()
        {
            return LoadSettings(_fileName);
            //if (!File.Exists(FileName))
            //{
            //    CreateEmptyFile(FileName);
            //}
            //XmlReader r = XmlReader.Create(FileName);
            //try
            //{
            //    _filesChanged.Clear();
            //    XmlDocument xmlDocument = new XmlDocument();
            //    xmlDocument.Load(r);
            //    XmlElement tmpNode = (XmlElement)xmlDocument.SelectSingleNode("/QOT");
            //    if (tmpNode.Attributes.Count <= 0)
            //        LoadOldSettingsFile(FileName);
            //    else
            //    {
            //        string ver = tmpNode.GetAttribute("version");
            //        switch (tmpNode.GetAttribute("version"))
            //        {
            //            case "1":
            //                {
            //                    LoadTheVersionedSettingsFile(xmlDocument);
            //                    break;
            //                }
            //            default:
            //                throw new Exception("Unrecognized file version.");
            //        }

            //    }
            //}
            //catch (Exception ex)
            //{
            //    if (ErrorEvent != null) ErrorEvent(this, ex);
            //    MessageBox.Show(ex.ToString(), "Warning!!");
            //    return false;
            //}
            //finally
            //{
            //    r.Close();
            //}
            //return true;
        }

        private bool LoadSettings(string fileName)
        {
            if (!File.Exists(fileName))
            {
                if (Directory.Exists(new FileInfo(fileName).DirectoryName))
                {
                    OnStatusChangeEventMethod(string.Format("Creating empty file: {0}", fileName));
                    //if (StatusChange != null) StatusChange("Creating empty file: " + fileName);
                    CreateEmptyFile(fileName);
                }
                else
                {
                    if (DialogResult.OK == MessageBox.Show("Location of this project not exists.\nIdentify new?", "Whrong project location!", MessageBoxButtons.OKCancel, MessageBoxIcon.Question))
                    {
                        using (OpenFileDialog filedial = new OpenFileDialog())
                        {
                            filedial.InitialDirectory = Settings.Instance.DefoultProjectLocation;
                            filedial.Multiselect = false;
                            filedial.Filter = string.Format("{1} ({0})|*{0}|All Files (*.*)|*.*", this.FileExtension, this.FileTypeName);
                            if (DialogResult.Cancel == filedial.ShowDialog())
                                return false;
                            fileName = filedial.FileName;
                            this._fileName = fileName;
                            base.OnProjectLocationChange(this);
                        }
                    }
                    else
                    {
                        return false;
                    }
                }
            }
            //System.Windows.Forms.MessageBox.Show(fileName);
            XmlReader r = XmlReader.Create(fileName);
            try
            {
                _filesChanged.Clear();
                _fileName = fileName;
                base._projectLocation = fileName.Remove(fileName.LastIndexOf('\\'));
                XmlDocument xmlDocument = new XmlDocument();
                OnStatusChangeEventMethod(string.Format("Opening project file from: {0}", fileName));
                //if (StatusChange != null) StatusChange("Opening project file from: " + fileName);
                xmlDocument.Load(r);
                XmlNamespaceManager xnm = new XmlNamespaceManager(xmlDocument.NameTable);
                //xnm.AddNamespace("xs", "urn:QueryOptimalizationTester-schema");
                XmlElement tmpNode = (XmlElement)xmlDocument.SelectSingleNode("/QOT", xnm);
                if (tmpNode.Attributes.Count <= 0)
                    LoadOldSettingsFile(fileName);
                else
                {
                    string ver = tmpNode.GetAttribute("version");
                    switch (tmpNode.GetAttribute("version"))
                    {
                        case "1":
                            {
                                LoadTheVersionedSettingsFile(xmlDocument);
                                break;
                            }
                        default:
                            throw new Exception("Unrecognized file version.");
                    }

                }
            }
            catch (Exception ex)
            {
                OnErrorEventMethod(this, ex);
                MessageBox.Show(ex.ToString(), "Warning!!");
                return false;
            }
            finally
            {
                r.Close();
            }
            return true;
        }

        private bool LoadOldSettingsFile(string fileName)
        {
            try
            {
                OnStatusChangeEventMethod(string.Format("Loading OLD settings: {0}", fileName));
                //if (StatusChange != null) StatusChange("Loading OLD settings: " + fileName);
                List<Server> tmpServerList = new List<Server>();
                Server a = new Server();
                string element = string.Empty;
                //int atrybutserver = -1;
                string atrybuttable = string.Empty;
                int atrybuttableid = -1;
                string atrybutprocedure = string.Empty;
                string atrybutindb = string.Empty;
                string atrybutdatabase = string.Empty;

                if (!File.Exists(fileName))
                {
                    CreateEmptyFile(fileName);
                }
                //XmlReader r = new XmlTextReader(_filename);
                XmlReader r = XmlReader.Create(fileName);
                while (r.Read())
                {
                    if (r.HasAttributes && (r.Name == "tmpserver" || r.Name == "server"))
                    {
                        //a.Add(new Server());
                        //atrybutserver = Convert.ToInt32(r.GetAttribute("id"));
                        a.ID = Convert.ToInt32(r.GetAttribute("id"));
                    }
                    //atrybut = Convert.ToInt32(r.GetAttribute("id"));
                    if (r.NodeType == XmlNodeType.Element)
                    {
                        if (base.ProjectName == null)
                        {
                            base.ProjectName = fileName.Remove(0, fileName.LastIndexOf('\\') + 1);
                            base.ProjectName = base.ProjectName.Remove(base.ProjectName.LastIndexOf('.'));
                            //System.Windows.Forms.MessageBox.Show(base.ProjectName);
                            base.ProjectLocation = fileName.Remove(fileName.LastIndexOf('\\'));
                            //System.Windows.Forms.MessageBox.Show(base.ProjectLocation);
                        }
                        //element = r.Name;
                        switch (r.Name)
                        {
                            case "address":
                                {
                                    a.Address = r.ReadString();
                                    break;
                                }
                            case "serverchecked":
                                {
                                    a.Checked = Convert.ToBoolean(r.ReadString());
                                    break;
                                }
                            case "serveruseinthisproject":
                                {
                                    a.UseInThisProject = Convert.ToBoolean(r.ReadString());
                                    break;
                                }
                            case "SSPI":
                                {
                                    a.SSPI = Convert.ToBoolean(r.ReadString());
                                    break;
                                }
                            case "login":
                                {
                                    a.Login = r.ReadString();
                                    break;
                                }
                            case "password":
                                {
                                    a.Password = r.ReadString();
                                    break;
                                }
                            case "queries":
                                {
                                    _queries = Convert.ToInt32(r.ReadString());
                                    break;
                                }
                            case "database":
                                {
                                    atrybutdatabase = r.ReadString();
                                    a.DataBase.Add(new DataBase(atrybutdatabase));
                                    a.DataBase.Find(d => d.Name == atrybutdatabase).Parent = a;
                                    break;
                                }
                            case "databasechecked":
                                {
                                    a.DataBase.Find(d => d.Name == atrybutdatabase).Checked = Convert.ToBoolean(r.ReadString());
                                    break;
                                }
                            case "table":
                                {
                                    //MessageBox.Show("filtermethod");
                                    if (r.HasAttributes)
                                    {
                                        atrybuttableid = Convert.ToInt32(r.GetAttribute("id"));
                                    }
                                    break;
                                }
                            case "tablename":
                                {
                                    atrybuttable = r.ReadString();
                                    a.DataBase.Find(d => d.Name == atrybutdatabase).Tables.Add(new Table());
                                    a.DataBase.Find(d => d.Name == atrybutdatabase).Tables.Find(t => t.Name == atrybuttable).ID = Convert.ToInt32(r.GetAttribute("id"));
                                    a.DataBase.Find(d => d.Name == atrybutdatabase).Tables.Find(t => t.Name == atrybuttable).Name = atrybuttable;
                                    a.DataBase.Find(d => d.Name == atrybutdatabase).Tables.Find(t => t.Name == atrybuttable).Parent = a.DataBase.Find(d => d.Name == atrybutdatabase);
                                    break;
                                }
                            case "tablechecked":
                                {
                                    a.DataBase.Find(d => d.Name == atrybutdatabase).Tables.Find(t => t.Name == atrybuttable).Checked = Convert.ToBoolean(r.ReadString());
                                    break;
                                }
                            case "createdate":
                                {
                                    a.DataBase.Find(d => d.Name == atrybutdatabase).Tables.Find(t => t.Name == atrybuttable).CreateDate = Convert.ToDateTime(r.ReadString());
                                    break;
                                }
                            case "count":
                                {
                                    a.DataBase.Find(d => d.Name == atrybutdatabase).Tables.Find(t => t.Name == atrybuttable).Count = Convert.ToInt32(r.ReadString());
                                    break;
                                }
                            case "mindate":
                                {
                                    a.DataBase.Find(d => d.Name == atrybutdatabase).Tables.Find(t => t.Name == atrybuttable).MinDate = Convert.ToDateTime(r.ReadString());
                                    break;
                                }
                            case "maxdate":
                                {
                                    a.DataBase.Find(d => d.Name == atrybutdatabase).Tables.Find(t => t.Name == atrybuttable).MaxDate = Convert.ToDateTime(r.ReadString());
                                    break;
                                }
                            case "refreshdate":
                                {
                                    a.DataBase.Find(d => d.Name == atrybutdatabase).Tables.Find(t => t.Name == atrybuttable).RefreshDate = Convert.ToDateTime(r.ReadString());
                                    break;
                                }
                            case "wasrefreshed":
                                {
                                    a.DataBase.Find(d => d.Name == atrybutdatabase).Tables.Find(t => t.Name == atrybuttable).WasRefreshed = Convert.ToBoolean(r.ReadString());
                                    break;
                                }
                            case "procedures":
                                {
                                    //MessageBox.Show("filtermethod");
                                    //if (r.HasAttributes);
                                    break;
                                }
                            case "procname":
                                {
                                    atrybutprocedure = r.ReadString();
                                    if (AddProcedure(atrybutprocedure))
                                    {
                                        //AddProcedure(atrybutprocedure);
                                    }
                                    break;
                                }
                            case "procedurechecked":
                                {
                                    //_procedures[atrybutprocedure].Checked = Convert.ToBoolean(r.ReadString());
                                    break;
                                }
                            case "creationdateinsql":
                                {
                                    //_procedures[atrybutprocedure].CreationDateInSQL = Convert.ToDateTime(r.ReadString());
                                    break;
                                }
                            case "looking":
                                {
                                    ((ProcedureInfo)_procedureList.Find(p => p.Name == atrybutprocedure)).Looking = Convert.ToBoolean(r.ReadString());
                                    break;
                                }
                            case "isopen":
                                {
                                    ((ProcedureInfo)_procedureList.Find(p => p.Name == atrybutprocedure)).IsOpen = Convert.ToBoolean(r.ReadString());
                                    break;
                                }
                            case "found":
                                {
                                    ((ProcedureInfo)_procedureList.Find(p => p.Name == atrybutprocedure)).Found = Convert.ToInt32(r.ReadString());
                                    break;
                                }
                            case "starttime":
                                {
                                    ((ProcedureInfo)_procedureList.Find(p => p.Name == atrybutprocedure)).StartTime = Convert.ToDateTime(r.ReadString());
                                    break;
                                }
                            case "endtime":
                                {
                                    ((ProcedureInfo)_procedureList.Find(p => p.Name == atrybutprocedure)).EndTime = Convert.ToDateTime(r.ReadString());
                                    break;
                                }
                            case "saved":
                                {
                                    ((ProcedureInfo)_procedureList.Find(p => p.Name == atrybutprocedure)).Saved = Convert.ToBoolean(r.ReadString());
                                    break;
                                }
                            /*
                            case "procedurefilelokalization":
                                {
                                    a[atrybutserver].database[atrybutdatabase].procedures[atrybutprocedure].FileLokalization = r.ReadString();
                                    break;
                                }
                            */
                            case "isinsert":
                                {
                                    //_procedures[atrybutprocedure].IsInsert = Convert.ToBoolean(r.ReadString());
                                    break;
                                }
                            case "isupdate":
                                {
                                    //_procedures[atrybutprocedure].IsUpdate = Convert.ToBoolean(r.ReadString());
                                    break;
                                }
                            case "istransaction":
                                {
                                    //_procedures[atrybutprocedure].IsTransaction = Convert.ToBoolean(r.ReadString());
                                    break;
                                }
                        }
                    }

                    if (r.NodeType == XmlNodeType.EndElement && (r.Name == "tmpserver" || r.Name == "server"))
                    {
                        //Console.WriteLine(r.NodeType);
                        tmpServerList.Add(a);
                        _servers = tmpServerList;
                        //Console.WriteLine("End of tmpserver: {0}", atrybut);
                    }
                }
                r.Close();
            }
            catch (Exception ex)
            {
                OnErrorEventMethod(this, ex);
                return false;
            }
            return true;
        }

        private bool LoadTheVersionedSettingsFile(XmlDocument xmlDocument)
        {
            try
            {
                bool hasname = false;
                //if (!File.Exists(FileName))
                //{
                //    CreateEmptyFile();
                //}
                //XMLParser(xmlDocument);
                XMLParser(xmlDocument);
                XmlNode testnode = xmlDocument.SelectSingleNode("/QOT/settings");
                _queries = Convert.ToInt32(testnode.Attributes["queries"].Value);
                base._projectName = testnode.Attributes["projectname"].Value;
                if (!hasname)
                {
                    base._projectName = base._fileName.Remove(0, base._fileName.LastIndexOf('\\') + 1);
                    base._projectName = base._projectName.Remove(base._projectName.LastIndexOf('.'));
                    //System.Windows.Forms.MessageBox.Show(base.ProjectName);
                    base.ProjectLocation = base._fileName.Remove(base._fileName.LastIndexOf('\\'));
                    //base.ProjectName = FileName.Remove(FileName.LastIndexOf('\\'));
                }
                if (!string.IsNullOrWhiteSpace(base._projectName))
                    hasname = true;
                OnStatusChangeEventMethod(string.Format("Load Setting for project: {0}", base._projectName));
                try
                {
                    System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(Library.Objects.ProjectSettings));
                    XmlDocument xd = new XmlDocument();
                    xd.Load(FileName + ".xml");
                    XmlNode tmpNode = xd.DocumentElement;
                    XmlReader r = new XmlNodeReader(tmpNode);
                    this.ReadXml(r);
                    //serializer.Deserialize(r);
                }
                catch { }
                //if (StatusChange != null) StatusChange("Load Setting for project: " + base._projectName);
                foreach (XmlAttribute tmpAttribute in testnode.Attributes)
                {
                    switch (tmpAttribute.Name)
                    {
                        case "projectname":
                            //base._projectName = testnode.Attributes["projectname"].Value;
                            //case "projectlocation":
                            //    if (testnode.Attributes["projectlocation"].Value != "" && Directory.Exists(testnode.Attributes["projectlocation"].Value))
                            //        base.ProjectLocation = testnode.Attributes["projectlocation"].Value;
                            break;
                        case "projectoldprocedurelocation":
                            AddObservedDirectories(testnode.Attributes["projectoldprocedurelocation"].Value);
                            break;
                        case "projectnewprocedurelocation":
                            AddObservedDirectories(testnode.Attributes["projectnewprocedurelocation"].Value);
                            break;
                        default:
                            break;
                    }
                }
                XmlNodeList xmlListDirectories = xmlDocument.SelectNodes("//observeddirectories/directory");
                foreach (XmlElement xmldir in xmlListDirectories)
                {
                    AddObservedDirectories(xmldir.GetAttribute("dir"));
                }
                XmlNodeList xmlListServers = xmlDocument.SelectNodes("//server");
                foreach (XmlElement xmlNodeServer in xmlListServers)
                {
                    if (!_servers.Exists(s=>s.Address == xmlNodeServer.GetAttribute("address")))
                    {
                        List<DataBase> tmpDataBaseList = new List<DataBase>();
                        Server tmpServer;
                        if (Convert.ToBoolean(xmlNodeServer.GetAttribute("SSPI")))
                            tmpServer = new Server(Convert.ToInt32(xmlNodeServer.GetAttribute("id")), xmlNodeServer.GetAttribute("address"), Convert.ToBoolean(xmlNodeServer.GetAttribute("SSPI")));
                        else
                            tmpServer = new Server(Convert.ToInt32(xmlNodeServer.GetAttribute("id")), xmlNodeServer.GetAttribute("address"), Convert.ToBoolean(xmlNodeServer.GetAttribute("SSPI")), xmlNodeServer.GetAttribute("login"), xmlNodeServer.GetAttribute("password"));
                        if (xmlNodeServer.HasAttribute("Type"))
                            tmpServer.Type = (Server.TypeOfServer)Enum.Parse(typeof(Server.TypeOfServer), xmlNodeServer.GetAttribute("Type"));
                        //XmlNodeList xmlListDataBases = xmlNodeServer.SelectNodes("/server[@id='" + serverid + "']/databases/database");
                        XmlDocument xmlDocumentServer = new XmlDocument();
                        if (!string.IsNullOrWhiteSpace(xmlNodeServer.InnerXml))
                        {
                            xmlDocumentServer.LoadXml(xmlNodeServer.InnerXml);
                            XmlNodeList xmlListDataBases = xmlDocumentServer.SelectNodes("//databases/database");
                            foreach (XmlElement xmlNodeDataBase in xmlListDataBases)
                            {
                                List<Table> tmpListTable = new List<Table>();
                                DataBase tmpDatabase = new DataBase(xmlNodeDataBase.GetAttribute("name"));

                                XmlDocument xmlDocumentDatabase = new XmlDocument();
                                if (!string.IsNullOrWhiteSpace(xmlNodeDataBase.InnerXml))
                                {
                                    xmlDocumentDatabase.LoadXml(xmlNodeDataBase.InnerXml);
                                    XmlNodeList xmlListTables = xmlDocumentDatabase.SelectNodes("//tables/table");
                                    foreach (XmlElement xmlNodeTable in xmlListTables)
                                    {
                                        tmpListTable.Add(
                                            new Table(Convert.ToInt32(xmlNodeTable.GetAttribute("id"))
                                                , xmlNodeTable.GetAttribute("name")
                                                , Convert.ToDateTime(xmlNodeTable.GetAttribute("createdate"))
                                                , Convert.ToInt32(xmlNodeTable.GetAttribute("count"))
                                                , Convert.ToDateTime(xmlNodeTable.GetAttribute("mindate"))
                                                , Convert.ToDateTime(xmlNodeTable.GetAttribute("maxdate"))
                                                , Convert.ToDateTime(xmlNodeTable.GetAttribute("refreshdate"))
                                                , Convert.ToBoolean(xmlNodeTable.GetAttribute("wasrefreshed"))));
                                        tmpListTable.Find(t => t.Name == xmlNodeTable.GetAttribute("name")).Checked = Convert.ToBoolean(xmlNodeTable.GetAttribute("tablechecked"));
                                        tmpListTable.Find(t => t.Name == xmlNodeTable.GetAttribute("name")).Parent = tmpDatabase;
                                        if (xmlNodeTable.HasAttribute("schema"))
                                            tmpListTable.Find(t => t.Name == xmlNodeTable.GetAttribute("name")).Schema = xmlNodeTable.GetAttribute("schema");
                                    }
                                    tmpDatabase.Tables = tmpListTable;
                                }
                                tmpDatabase.Parent = tmpServer;
                                tmpDatabase.Checked = Convert.ToBoolean(xmlNodeDataBase.GetAttribute("databasechecked"));
                                tmpDataBaseList.Add(tmpDatabase);
                            }
                            tmpServer.DataBase = tmpDataBaseList;
                        }
                        tmpServer.UseInThisProject = Convert.ToBoolean(xmlNodeServer.GetAttribute("serveruseinthisproject"));
                        tmpServer.Checked = Convert.ToBoolean(xmlNodeServer.GetAttribute("serverchecked"));
                        _servers.Add(tmpServer); 
                    }
                }

                XmlNodeList xmlListProcedures = xmlDocument.SelectNodes("//procedures/procedure");
                //Dictionary<string, ProcedureResultInformation> tmpProc = new Dictionary<string, ProcedureResultInformation>();
                foreach (XmlElement xmlNodeProcedure in xmlListProcedures)
                {
                    ProcedureInfo tmpproc = new ProcedureInfo(xmlNodeProcedure.GetAttribute("name"), Convert.ToBoolean(xmlNodeProcedure.GetAttribute("isopen")), Convert.ToBoolean(xmlNodeProcedure.GetAttribute("looking")), Convert.ToInt32(xmlNodeProcedure.GetAttribute("found")), Convert.ToDateTime(xmlNodeProcedure.GetAttribute("starttime")), Convert.ToDateTime(xmlNodeProcedure.GetAttribute("endtime")));
                    tmpproc.ResultFile = xmlNodeProcedure.GetAttribute("ResultFile");
                    bool b;
                    Boolean.TryParse(xmlNodeProcedure.GetAttribute("StartFromTheLatestData"), out b);
                    tmpproc.StartFromTheLatestData = b;
                    DateTime date;
                    DateTime.TryParse(xmlNodeProcedure.GetAttribute("DateOfLastDataFound"), out date);
                    tmpproc.DateOfLastDataFound = date;

                    if (AddProcedure(tmpproc) && !string.IsNullOrWhiteSpace(xmlNodeProcedure.InnerXml))
                    {
                        XmlNodeList xmlListVersions = xmlNodeProcedure.SelectNodes("//procedures/procedure[@id=" + xmlNodeProcedure.GetAttribute("id") + "]/version");
                        foreach (XmlElement xmlNodeVersion in xmlListVersions)
                        {
                            XmlDocument xmlDocumentVersion = new XmlDocument();
                            xmlDocumentVersion.LoadXml(xmlNodeVersion.InnerText);
                            IProcedure tmpprocff = null;
                            try
                            {
                                switch (xmlDocumentVersion.DocumentElement.Name)
                                {
                                    case "ProcedureFromFile":
                                        tmpprocff = new ProcedureFromFile();
                                        //tmpprocff.Marge(tmpprocff.Deserialize<ProcedureFromFile>(xmlNodeVersion.InnerText));
                                        var tmpf = tmpprocff.Deserialize<ProcedureFromFile>(xmlNodeVersion.InnerText);
                                        tmpf.LoadedFromSettings = true;
                                        tmpprocff.LoadedFromSettings = true;
                                        tmpprocff.Marge(tmpf);
                                        tmpprocff.Source = _fileName;
                                        foreach (ProcedureVersion tmpver in tmpprocff.ProcVersionList)
                                            tmpver.Parent = tmpprocff;
                                        tmpprocff.Parent = tmpproc;
                                        tmpprocff.LoadedFromSettings = false;
                                        tmpproc.SetProcDetailsFromFile((ProcedureFromFile)tmpprocff);
                                        break;
                                    case "ProcedureFromDatabase":
                                        try
                                        {
                                            tmpprocff = new ProcedureFromDatabase();
                                            var tmpd = tmpprocff.Deserialize<ProcedureFromDatabase>(xmlNodeVersion.InnerText);
                                            tmpd.LoadedFromSettings = true;
                                            tmpprocff.LoadedFromSettings = true;
                                            tmpprocff.Marge(tmpd);
                                            tmpprocff.Source = _fileName;
                                            foreach (ProcedureVersion tmpver in tmpprocff.ProcVersionList)
                                                tmpver.Parent = tmpprocff;
                                            Library.Objects.Server tmpserv = _servers.Exists(s => s.Address == ((ProcedureFromDatabase)tmpprocff).Server) ? _servers.Find(s => s.Address == ((ProcedureFromDatabase)tmpprocff).Server) : new Server(((ProcedureFromDatabase)tmpprocff).Server);
                                            if (!_servers.Exists(s => s == tmpserv)) _servers.Add(tmpserv);
                                            Library.Objects.DataBase tmpdatabase = tmpserv.DataBase.Exists(d => d.Name == ((ProcedureFromDatabase)tmpprocff).DataBase) ? tmpserv.DataBase.Find(d => d.Name == ((ProcedureFromDatabase)tmpprocff).DataBase) : new DataBase(((ProcedureFromDatabase)tmpprocff).DataBase);
                                            if (tmpdatabase.Parent == null) tmpdatabase.Parent = tmpserv;
                                            if (!tmpserv.DataBase.Exists(d => d == tmpdatabase)) tmpserv.DataBase.Add(tmpdatabase);
                                            foreach (ProcedureVersion tmpver in tmpprocff.ProcVersionList)
                                                tmpver.Parent = tmpprocff;
                                            ((ProcedureFromDatabase)tmpprocff).Parent = tmpproc;
                                            tmpprocff.LoadedFromSettings = false;
                                            tmpproc.SetProcDetailsFromBase((ProcedureFromDatabase)tmpprocff);
                                        }
                                        catch { }
                                        break;
                                    default:
                                        OnErrorEventMethod(this, new Exception(string.Format("Unrecognized type \"{0}\"", xmlDocumentVersion.DocumentElement.Name)));
                                        break;
                                }
                            }
                            catch (Exception)
                            {
                                throw;
                            }
                        }
                    }
                    //AddProcedure(tmpproc);
                }
            }
            catch (Exception ex)
            {
                OnErrorEventMethod(this, ex);
                MessageBox.Show(ex.ToString(), "Warning!!");
                return false;
            }
            return true;
        }

        public Boolean Save()
        {
            if (!_isLoaded || string.IsNullOrWhiteSpace(FileName))
            { return false; }
            FileInfo fsInfo;
            bool _readonly;
            try
            {
                fsInfo = new FileInfo(FileName);
                _readonly = false;
                if (fsInfo.Exists)
                {
                    if (fsInfo.IsReadOnly)
                    {
                        _readonly = true;
                        if (DialogResult.OK == MessageBox.Show("File is read only.", "Warning!!", MessageBoxButtons.OKCancel, MessageBoxIcon.Asterisk))
                        {
                            fsInfo.IsReadOnly = false;
                        }
                        else
                        {
                            return false;
                        }
                    }
                }
                else
                {
                    DialogResult dial = MessageBox.Show("File \"" + FileName + "\" not exists. Find localization(YES) or creane new.", "Warning!! File not exists", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
                    switch (dial)
                    {
                        case DialogResult.No:
                            {
                                char[] c = { '\\' };

                                string tmpDirectory = FileName.Remove(FileName.LastIndexOfAny(c));
                                if (!Directory.Exists(tmpDirectory))
                                {
                                    Directory.CreateDirectory(tmpDirectory);
                                }
                                break;
                            }
                        case DialogResult.Yes:
                            {
                                SaveFileDialog filedial = new SaveFileDialog();
                                filedial.Filter = "QOT File (*.qot)|*.qot";
                                //filedial.Multiselect = false;
                                filedial.ShowDialog();
                                if (filedial.FileName.Length > 0)
                                    FileName = filedial.FileName;
                                else
                                    return false;
                                break;
                            }
                        default:
                            {
                                return false;
                            }
                    }
                }
            }
            catch (Exception ex)
            {
                OnErrorEventMethod(this, ex);
                MessageBox.Show(ex.Message);
                NotSaved();
                return false;
            }
            using (FileStream fs = new FileStream(FileName, FileMode.Create))
            {
                try
                {
                    SaveXMLProjectToFile(fs);
                    SaveAsXML(fs);
                    if (_readonly)
                    {
                        fsInfo.IsReadOnly = true;
                    }
                    IsSaved();
                }
                catch (Exception ex)
                {
                    OnErrorEventMethod(this, ex);
                    MessageBox.Show(ex.Message);
                    NotSaved();
                    return false;
                }
                finally
                {
                    fs.Close();
                }
                //}
                return true;
            }
        }

        private void SaveXMLProjectToFile(FileStream fs)
        {
            using (XmlTextWriter xml = new XmlTextWriter(fs, Encoding.UTF8))
            {
                //XmlWriter xml = XmlWriter.Create(fs, Encoding.UTF8);
                xml.Formatting = Formatting.Indented;
                xml.Namespaces = true;

                int i = 0;
                int j = 0;
                int k = 0;

                xml.WriteStartDocument();
                //xml.WriteStartElement("ROOT","xs");
                //xml.WriteStartElement("xs", "QOT", "urn:QueryOptimalizationTester-schema");
                xml.WriteStartElement("QOT");
                xml.WriteAttributeString("version", "1");
                //xml.WriteAttributeString("xmlns:xs", "http://www.w3.org/2001/XMLSchema-instance");
                //xml.WriteEndElement();
                xml.WriteStartElement("settings");
                xml.WriteAttributeString("queries", _queries.ToString());
                xml.WriteAttributeString("projectname", base.ProjectName);
                xml.WriteAttributeString("projectlocation", base.ProjectLocation);
                xml.WriteStartElement("observeddirectories");
                foreach (ObservedDirectory str in _observedDirectories)
                {
                    xml.WriteStartElement("directory");
                    xml.WriteAttributeString("dir", str.Directory);
                    xml.WriteEndElement();
                }
                xml.WriteEndElement();
                xml.WriteStartElement("servers");
                foreach (Server tmpserver in _servers)
                {
                    if (tmpserver.UseInThisProject)
                    {
                        xml.WriteStartElement("server");
                        xml.WriteAttributeString("id", i.ToString());
                        xml.WriteAttributeString("address", tmpserver.Address.ToString());
                        xml.WriteAttributeString("serverchecked", tmpserver.Checked.ToString());
                        xml.WriteAttributeString("serveruseinthisproject", tmpserver.UseInThisProject.ToString());
                        xml.WriteAttributeString("SSPI", tmpserver.SSPI.ToString());
                        xml.WriteAttributeString("Type", tmpserver.Type.ToString());
                        if (!tmpserver.SSPI)
                        {
                            if (tmpserver.Login != null)
                            {
                                xml.WriteAttributeString("login", tmpserver.Login.ToString());
                                xml.WriteAttributeString("password", tmpserver.Password.ToString());
                            }
                        }
                        //xml.WriteStartElement("procedures");
                        //xml.WriteEndElement();
                        //xml.WriteElementString("database", tmpserver.database.ToString());
                        if (tmpserver.DataBase.Count > 0)
                        {
                            xml.WriteStartElement("databases");
                            j = 0;
                            foreach (DataBase tmpdatabase in tmpserver.DataBase)
                            {
                                k = 0;
                                xml.WriteStartElement("database");
                                xml.WriteAttributeString("id", j.ToString());
                                xml.WriteAttributeString("name", tmpdatabase.Name.ToString());
                                xml.WriteAttributeString("databasechecked", tmpdatabase.Checked.ToString());
                                if (tmpdatabase.Tables.Count > 0)
                                {
                                    xml.WriteStartElement("tables");
                                    foreach (Table tmptabele in tmpdatabase.Tables)
                                    {
                                        xml.WriteStartElement("table");
                                        xml.WriteAttributeString("id", k.ToString());
                                        xml.WriteAttributeString("name", tmptabele.Name.ToString());
                                        xml.WriteAttributeString("schema", tmptabele.Schema.ToString());
                                        xml.WriteAttributeString("tablechecked", tmptabele.Checked.ToString());
                                        xml.WriteAttributeString("createdate", tmptabele.CreateDate.ToShortDateString().ToString());
                                        xml.WriteAttributeString("count", tmptabele.Count.ToString());
                                        xml.WriteAttributeString("mindate", tmptabele.MinDate.ToString());
                                        xml.WriteAttributeString("maxdate", tmptabele.MaxDate.ToString());
                                        xml.WriteAttributeString("refreshdate", tmptabele.RefreshDate.ToString());
                                        xml.WriteAttributeString("wasrefreshed", tmptabele.WasRefreshed.ToString());
                                        xml.WriteEndElement();
                                        k++;
                                    }
                                    xml.WriteEndElement();
                                }
                                xml.WriteEndElement();
                                j++;
                            }
                            i++;
                            xml.WriteEndElement();
                        }
                        xml.WriteEndElement();
                        //xml.WriteEndElement(); 
                    }
                }
                xml.WriteEndElement();
                //xml.WriteEndElement();

                xml.WriteStartElement("procedures");
                i = 0;
                foreach (ProcedureInfo tmpprocedures in _procedureList)
                {
                    xml.WriteStartElement("procedure");
                    xml.WriteAttributeString("id", i.ToString());
                    xml.WriteAttributeString("name", tmpprocedures.Name.ToString());
                    xml.WriteAttributeString("looking", tmpprocedures.Looking.ToString());
                    xml.WriteAttributeString("isopen", tmpprocedures.IsOpen.ToString());
                    xml.WriteAttributeString("saved", tmpprocedures.Saved.ToString());
                    xml.WriteAttributeString("found", tmpprocedures.Found.ToString());
                    xml.WriteAttributeString("starttime", tmpprocedures.StartTime.ToString());
                    xml.WriteAttributeString("endtime", tmpprocedures.EndTime.ToString());
                    xml.WriteAttributeString("ResultFile", tmpprocedures.ResultFile);
                    xml.WriteAttributeString("StartFromTheLatestData", tmpprocedures.StartFromTheLatestData.ToString());
                    xml.WriteAttributeString("DateOfLastDataFound", tmpprocedures.DateOfLastDataFound.ToString());
                    if (tmpprocedures.ProcedureList.Count > 0)
                    {
                        foreach (IProcedure ip in tmpprocedures.ProcedureList)
                        {
                            var nsSerializer = new XmlSerializerNamespaces();
                            nsSerializer.Add("", "");

                            var xmlSerializer = new System.Xml.Serialization.XmlSerializer(ip.GetType(), "");
                            xmlSerializer.Serialize(xml, ip, nsSerializer);
                        }
                    }
                    if (tmpprocedures.SearchedObjectsList.Count > 0)
                    {
                        foreach (SearchedObject tmpobj in tmpprocedures.SearchedObjectsList)
                        {
                            var nsSerializer = new XmlSerializerNamespaces();
                            nsSerializer.Add("", "");

                            var xmlSerializer = new System.Xml.Serialization.XmlSerializer(tmpobj.GetType(), "");
                            xmlSerializer.Serialize(xml, tmpobj, nsSerializer);
                        }
                    }
                    xml.WriteEndElement();
                    i++;
                }
                xml.WriteEndElement();
                xml.WriteEndElement();
                //xml.WriteEndElement();
                xml.WriteEndDocument();
                xml.Flush();
            }
        }

        private void SaveAsXML(FileStream fs)
        {
            MemoryStream w = new MemoryStream();
            StreamWriter strw = new StreamWriter(FileName + ".xml", false);
            //System.Runtime.Serialization.Formatters.Binary.BinaryFormatter t = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(
            System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(typeof(ProjectSettings));
            x.Serialize(strw, this, null);
            //w.Flush();
            //string text = w.ToString();
            
            strw.Close();
        }

        //public delegate string[]
        //public QuestionEventHandler q;

        public bool Start()
        {
            try
            {
                OnStatusChangeEventMethod("The search process began");


                Settings.Instance.ProjectSettings.CheckAndRefreshAllSelectedTables();

                if (!CheckDateAndTable() || !CheckData())
                {
                    OnStatusChangeEventMethod("Search process cancelled by User.");
                    return false;
                }

                foreach (Library.Objects.IProcedureInfo tmpProc in this._procedureList)
                {
                    if (CheckIfCanStartLookForProcedure((Library.Objects.ProcedureInfo)tmpProc))
                    {
                        tmpProc.Start();
                    }
                    else
                    {
                        _queue.Enqueue(tmpProc);
                    }
                    if (ForceStop)
                        break;
                }
                //EndProces();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Warning!!");
                OnErrorEventMethod(ex.Message, ex);
                //_errolog.AddError(new Panels.VerificationLogItem(ex, this));
            }
            return true;
        }

        /// <summary>
        /// It is Checking whether it can start looking for a procedure
        /// </summary>
        /// <param name="procedure">Name of procedure you whant too seek</param>
        /// <returns></returns>
        public bool CheckIfCanStartLookForProcedure(Library.Objects.ProcedureInfo procedure)
        {
            //foreach (DataGridViewRow tmpRow in dataGridView_LookingProcedures.Rows)
            //{
            //    //Debug.WriteLine(tmpRow.Cells[QuerySearchingStatus.Name].Value.ToString().Trim());
            //    if (tmpRow.Cells[QuerySearchingStatus.Name].Value.ToString().Trim() == Library.Objects.ProcedureInfo.Status.Started.ToString().Trim())
            //    {
            //        RunnigProcesses++;
            //    }
            //}
            int MaxRouningProcess = Settings.Instance.MaxRouningProcess;
            if (_runnigProcesses < MaxRouningProcess)
            {
                return procedure.Looking;
            }
            else
            {
                return false;
            }
        }

        public bool CheckDateAndTable()
        {
            try
            {
                DateTime min = DateTime.MaxValue;
                DateTime max = DateTime.MinValue;
                DialogResult dial;
                List<object> notrefreshedtable = new List<object>();
                foreach (Library.Objects.Server tmpserver in _servers)
                {
                    if (tmpserver.Checked)
                        if (tmpserver.ConnectionEstablished)
                        {
                            notrefreshedtable.Clear();
                            foreach (Library.Objects.DataBase tmptadabase in tmpserver.DataBase)
                            {
                                if (tmptadabase.Checked)
                                {
                                    foreach (Library.Objects.Table tmptable in tmptadabase.Tables)
                                    {
                                        if (tmptable.Checked)
                                        {
                                            if (tmptable.RefreshDate < System.DateTime.Now.AddDays(-30) || !tmptable.WasRefreshed)
                                            {
                                                notrefreshedtable.Add(tmptable);
                                                //dial = MessageBox.Show("Last refresh date of table was 30 days ago", "Warning!", MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk);
                                                //if (dial == DialogResult.Yes) throw new NotImplementedException("Not jet implemented");
                                            }
                                            if (tmptable.WasRefreshed && (min > tmptable.MinDate) && (tmptable.MinDate != DateTime.MinValue)) min = tmptable.MinDate;
                                            if (tmptable.WasRefreshed && (max < tmptable.MaxDate) && (tmptable.MaxDate != DateTime.MaxValue)) max = tmptable.MaxDate;
                                        }
                                    }
                                    if (notrefreshedtable.Count != 0)
                                    {

                                        using (frmQuestion questionwindow = new frmQuestion("Last refresh date of table was 30 days ago", "Warning!", notrefreshedtable))
                                        {
                                            //if (this.InvokeRequired)
                                            //    this.BeginInvoke((MethodInvoker)delegate
                                            //    {
                                            //        questionwindow.ShowDialog(this.Parent);
                                            //    });
                                            //else
                                            questionwindow.ShowDialog();

                                            if (questionwindow.Result != null && questionwindow.Result.Count != 0)
                                                foreach (object tmpobject in questionwindow.Result)
                                                {
                                                    //notrefreshedtable.Add((Table)tmpobject);

                                                    Library.Scripts.GetFromSQL.GetInfoOfTable(tmpserver, tmptadabase, (Library.Objects.Table)tmpobject);

                                                    if ((min > ((Library.Objects.Table)tmpobject).MinDate) && (((Library.Objects.Table)tmpobject).MinDate != DateTime.MinValue)) min = ((Library.Objects.Table)tmpobject).MinDate;
                                                    if ((max < ((Library.Objects.Table)tmpobject).MaxDate) && (((Library.Objects.Table)tmpobject).MaxDate != DateTime.MaxValue)) max = ((Library.Objects.Table)tmpobject).MaxDate;
                                                }
                                        }

                                    }
                                }
                            }
                        }
                }

                if ((_datestop < min || _datestart > max) && min != DateTime.MaxValue && max != DateTime.MinValue)
                {
                    dial = MessageBox.Show("Date range of data from the tables is not compatible with a selected range\n" +
                        "Enter the dates of the entire range?\n\n" + min + " - " + max, "Warning!!", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);

                    switch (dial)
                    {
                        case DialogResult.Yes:
                            {
                                this.DateStart = min;
                                this.DateStop = max.AddDays(1); ;
                                //if (this.InvokeRequired)
                                //    this.BeginInvoke((MethodInvoker)delegate
                                //    {
                                //        _diferentsForDates = (max.Month - min.Month);
                                //        //dateTimePicker_Start.Value = min;
                                //        _datestop = max.AddDays(1).ToShortDateString();
                                //    });
                                //else
                                //{
                                _diferentsForDates = (max.Month - min.Month);
                                //dateTimePicker_Start.Value = min;
                                //_datestop = max.AddDays(1);
                                //}
                                //ProjectSettings.DateStart = dateTimePicker_Start.Value.ToShortDateString();
                                //ProjectSettings.DateStop = dateTimePicker_End.Value.ToShortDateString();
                                return true;
                            }
                        case DialogResult.Cancel:
                            {
                                return false;
                            }
                        default:
                            {
                                return true;
                            }
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), ex.Source);
                OnErrorEventMethod(this, ex);
                return true;
            }
            finally
            {
                //return DialogResult.Cancel;
            }

        }

        /// <summary>
        /// checs if insertet data are corect
        /// </summary>
        /// <returns></returns>
        public bool CheckData()
        {
            //foreach (Control control in Controls)
            //{
            //    control.Select();
            //    if (!Validate())
            //    {
            //        return false;
            //    }
            //}

            if (_procedureList.Count == 0)
            {
                OnStatusChangeEventMethod("Enter at least one procedure.");
                MessageBox.Show("Enter at least one procedure.", "Warning!!", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return false;
            }
            else
            {
                //string messagetext = "You have not provided the procedure\n";

                //if ((_notsaveProcedure != string.Empty))
                //{
                //    if (_notsaveProcedure != string.Empty) messagetext += _notsaveProcedure + "\r\n";

                //    messagetext += "\nDo you whant to continue anyway?";
                //    if (MessageBox.Show(messagetext, "Warning!!", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.No)
                //    {
                //        return false;
                //    }
                //}
            }
            return true;
        }

        /// <summary>
        /// Pobiera tylko kolumny
        /// </summary>
        /// <returns></returns>
        public bool CheckAndRefreshAllSelectedTables()
        {
            //TODO Poprawić odświerzanie informacji na temat tabel
            foreach (Library.Objects.Server tmpserver in this.Servers)
            {
                if (tmpserver.Checked)
                    if (tmpserver.ConnectionEstablished)
                    {
                        foreach (Library.Objects.DataBase tmpdatabase in tmpserver.DataBase)
                        {
                            if (tmpdatabase.Checked)
                                foreach (Library.Objects.Table tmptable in tmpdatabase.Tables)
                                {
                                    if (tmptable.Checked)
                                        if (tmptable.Columns.Count == 0)
                                        {
                                            //if (tmptable.RefreshDate < DateTime.Now.AddDays(-30))
                                            Library.Scripts.GetFromSQL.GetColumnsFromTable(tmpserver, tmpdatabase, tmptable);
                                        }
                                }
                        }
                    }
            }
            return true;
        }

        private void ShowCompileErrors(object sender, ValidationEventArgs e)
        {
            switch (e.Severity)
            {
                case XmlSeverityType.Error:
                    {
                        OnErrorEventMethod(sender, e.Exception);
                        break;
                    }
                case XmlSeverityType.Warning:
                    {
                        OnStatusChangeEventMethod(string.Format("Line: {0}, Position: {1} \"{2}\"", e.Exception.LineNumber, e.Exception.LinePosition, e.Exception.Message));
                        break;
                    }
            }
            //if (e.Severity == XmlSeverityType.Error || e.Severity == XmlSeverityType.Warning)
            //    if (ErrorEvent != null) ErrorEvent(String.Format("Line: {0}, Position: {1} \"{2}\"", e.Exception.LineNumber, e.Exception.LinePosition, e.Exception.Message), e.Exception);
            //MessageBox.Show(args.Message+ Environment.NewLine + args.Exception, "Validation Error: {0}");
        }

        private Boolean XMLParser(XmlDocument xmlDocument)
        {
            try
            {
                XmlReaderSettings settings = new XmlReaderSettings();
                settings.CloseInput = true;
                settings.Schemas.Add("", Settings.Instance.ProgramLocalization + "\\Project Settings XMLSchema.xsd");
                settings.ValidationType = ValidationType.Schema;
                settings.ValidationEventHandler += new System.Xml.Schema.ValidationEventHandler(ShowCompileErrors);
                settings.ValidationFlags =
                     XmlSchemaValidationFlags.ReportValidationWarnings |
                XmlSchemaValidationFlags.ProcessIdentityConstraints |
                XmlSchemaValidationFlags.ProcessInlineSchema |
                XmlSchemaValidationFlags.ProcessSchemaLocation;
                //XmlDocument document = new XmlDocument();
                //document.Load(xmlFilePath);
                XmlReader rdr = XmlReader.Create(new StringReader(xmlDocument.InnerXml), settings);

                while (rdr.Read())
                {
#if DEBUG
                    OnStatusChangeEventMethod(string.Format("Validating field: ", rdr.Name));
#endif
                }
            }
            catch(FileNotFoundException fex)
                {
                    OnErrorEventMethod(this, fex);
                }
            return true;
        }

        private void CreateEmptyFile(string file)
        {
            using (
                   FileStream fs = new FileStream(file, FileMode.Create))
            {
                try
                {
                    XmlTextWriter xml = new XmlTextWriter(fs, Encoding.UTF8);
                    //XmlWriter xml = XmlWriter.Create(fs, Encoding.UTF8);
                    xml.Formatting = Formatting.Indented;
                    xml.Namespaces = true;

                    int i = 0;
                    int j = 0;
                    int k = 0;

                    xml.WriteStartDocument();
                    //xml.WriteStartElement("ROOT","xs");
                    //xml.WriteStartElement("xs", "QOT", "urn:QueryOptimalizationTester-schema");
                    xml.WriteStartElement("QOT");
                    xml.WriteAttributeString("version", "1");
                    //xml.WriteAttributeString("xmlns:xs", "http://www.w3.org/2001/XMLSchema-instance");
                    //xml.WriteEndElement();
                    xml.WriteStartElement("settings");
                    xml.WriteAttributeString("queries", _queries.ToString());
                    xml.WriteAttributeString("projectname", base.ProjectName);
                    xml.WriteAttributeString("projectlocation", base.ProjectLocation);
                    xml.WriteStartElement("observeddirectories");
                    foreach (ObservedDirectory str in _observedDirectories)
                    {
                        xml.WriteStartElement("directory");
                        xml.WriteAttributeString("dir", "");
                        xml.WriteEndElement();
                    }
                    xml.WriteEndElement();
                    xml.WriteStartElement("servers");
                    foreach (Server tmpserver in _servers)
                    {
                        if (tmpserver.UseInThisProject)
                        {
                            xml.WriteStartElement("server");
                            xml.WriteAttributeString("id", i.ToString());
                            xml.WriteAttributeString("address", tmpserver.Address.ToString());
                            xml.WriteAttributeString("serverchecked", tmpserver.Checked.ToString());
                            xml.WriteAttributeString("serveruseinthisproject", tmpserver.UseInThisProject.ToString());
                            xml.WriteAttributeString("SSPI", tmpserver.SSPI.ToString());
                            if (!tmpserver.SSPI)
                            {
                                if (tmpserver.Login != null)
                                {
                                    xml.WriteAttributeString("login", tmpserver.Login.ToString());
                                    xml.WriteAttributeString("password", tmpserver.Password.ToString());
                                }
                            }
                            if (tmpserver.DataBase.Count > 0)
                            {
                                xml.WriteStartElement("databases");
                                j = 0;
                                foreach (DataBase tmpdatabase in tmpserver.DataBase)
                                {
                                    k = 0;
                                    xml.WriteStartElement("database");
                                    xml.WriteAttributeString("id", j.ToString());
                                    xml.WriteAttributeString("name", tmpdatabase.Name.ToString());
                                    xml.WriteAttributeString("databasechecked", tmpdatabase.Checked.ToString());
                                    if (tmpdatabase.Tables.Count > 0)
                                    {
                                        xml.WriteStartElement("tables");
                                        foreach (Table tmptabele in tmpdatabase.Tables)
                                        {
                                            xml.WriteStartElement("table");
                                            xml.WriteAttributeString("id", k.ToString());
                                            xml.WriteAttributeString("name", tmptabele.Name.ToString());
                                            xml.WriteAttributeString("schema", tmptabele.Schema.ToString());
                                            xml.WriteAttributeString("tablechecked", tmptabele.Checked.ToString());
                                            xml.WriteAttributeString("createdate", tmptabele.CreateDate.ToShortDateString().ToString());
                                            xml.WriteAttributeString("count", tmptabele.Count.ToString());
                                            xml.WriteAttributeString("mindate", tmptabele.MinDate.ToString());
                                            xml.WriteAttributeString("maxdate", tmptabele.MaxDate.ToString());
                                            xml.WriteAttributeString("refreshdate", tmptabele.RefreshDate.ToString());
                                            xml.WriteAttributeString("wasrefreshed", tmptabele.WasRefreshed.ToString());
                                            xml.WriteEndElement();
                                            k++;
                                        }
                                        xml.WriteEndElement();
                                    }
                                    xml.WriteEndElement();
                                    j++;
                                }
                                i++;
                                xml.WriteEndElement();
                            }
                            xml.WriteEndElement();
                            //xml.WriteEndElement(); 
                        }
                    }
                    xml.WriteEndElement();
                    //xml.WriteEndElement();

                    xml.WriteStartElement("procedures");
                    i = 0;
                    foreach (ProcedureInfo tmpprocedures in _procedureList)
                    {
                        xml.WriteStartElement("procedure");
                        xml.WriteAttributeString("id", i.ToString());
                        xml.WriteAttributeString("name", tmpprocedures.Name.ToString());
                        //xml.WriteElementString("procedurechecked", tmpprocedures.Value.Checked.ToString());
                        xml.WriteAttributeString("looking", tmpprocedures.Looking.ToString());
                        xml.WriteAttributeString("isopen", tmpprocedures.IsOpen.ToString());
                        xml.WriteAttributeString("saved", tmpprocedures.Saved.ToString());
                        xml.WriteAttributeString("found", tmpprocedures.Found.ToString());
                        xml.WriteAttributeString("starttime", tmpprocedures.StartTime.ToString());
                        xml.WriteAttributeString("endtime", tmpprocedures.EndTime.ToString());
                        if (tmpprocedures.ProcedureList.Count > 0)
                        {
                            xml.WriteStartElement("proc");
                            foreach (IProcedure ip in tmpprocedures.ProcedureList)
                            {
                                xml.WriteString(ip.Serialize());
                            }
                            xml.WriteEndElement();
                        }
                        xml.WriteEndElement();
                        i++;
                    }
                    xml.WriteEndElement();
                    xml.WriteEndElement();
                    //xml.WriteEndElement();
                    xml.WriteEndDocument();
                    xml.Flush();
                    //if (_readonly)
                    //{
                    //    fsInfo.IsReadOnly = true;
                    //}
                    IsSaved();
                }
                catch (Exception ex)
                {
                    OnErrorEventMethod(this, ex);
                    MessageBox.Show(ex.Message);
                    NotSaved();
                    //return false;
                }
                finally
                {
                    fs.Close();
                }
            }
        }

        public List<Server> MargeConnectionSettings(List<Server> ServerList)
        {
            try
            {
                //#if DEBUG
                //#endif
                if (object.ReferenceEquals(_servers, ServerList))
                    OnErrorEventMethod(_servers, new Exception("Objects are identicall"));
                else
                {
                    foreach (Server tmpserver in ServerList)
                        if (_servers.Exists(s => s.Name == tmpserver.Name))
                        {
                            _servers.Find(s => s.Name == tmpserver.Name).Checked = (_servers.Find(s => s.Name == tmpserver.Name).Checked || tmpserver.Checked);
                            //if (_servers.Find(s=>s.Name==tmpserver.Name).Checked || tmpserver.Checked) _servers[tmpserver.Key].Checked = true; else _servers[tmpserver.Key].Checked = false;
                            _servers.Find(s => s.Name == tmpserver.Name).Marge(tmpserver);
                        }
                        else
                        {
                            _servers.Add(tmpserver);
                        }
                }

            }
            catch (Exception ex)
            {
                OnErrorEventMethod(ServerList, ex);
            }
            return _servers;
        }

        /// <summary>
        /// Ustawia status okna na "not saved"
        /// </summary>
        public void NotSaved()
        {
            if (_saved)
            {
                _saved = false;
                if (SaveStatusChanche != null) SaveStatusChanche(_saved);
            }
        }

        /// <summary>
        /// Ustawia status okna na "saved"
        /// </summary>
        private void IsSaved()
        {
            if (!_saved)
            {
                _saved = true;
                if (SaveStatusChanche != null) SaveStatusChanche(_saved);
            }
        }

        /// <summary>
        /// Add tracking for changes in folder for sql files witch sub directories
        /// </summary>
        /// <param name="directory">Path to folder</param>
        public void AddSetFileWatcher(string directory)
        {
            AddSetFileWatcher(directory, "*.SQL");
        }
        /// <summary>
        /// Add tracking for changes in folder witch sub directories
        /// </summary>
        /// <param name="directory">Path to folder</param>
        /// <param name="filter">Filter for watching files</param>
        public void AddSetFileWatcher(string directory, string filter)
        {
            AddSetFileWatcher(directory, filter, true, _searchFolderImmediately);
        }
        /// <summary>
        /// Add tracking for changes in folder
        /// </summary>
        /// <param name="directory">Path to folder</param>
        /// <param name="filter">Filter for watching files</param>
        /// <param name="IncludeSubdirectories">If include sub directories</param>
        /// <param name="SearchImmediately">If check folder immediately</param>
        public void AddSetFileWatcher(string directory, string filter, bool IncludeSubdirectories, bool SearchImmediately)
        {
            FileSystemWatcher filewatcher = new FileSystemWatcher(directory, filter);

            filewatcher = new FileSystemWatcher(directory, filter);
            filewatcher.Changed += new FileSystemEventHandler(FileWatcher_Changed);
            filewatcher.Created += new FileSystemEventHandler(FileWatcher_Created);
            filewatcher.Renamed += new RenamedEventHandler(FileWatcher_Renamed);
            filewatcher.IncludeSubdirectories = IncludeSubdirectories;
            filewatcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
                | NotifyFilters.FileName | NotifyFilters.DirectoryName;
            filewatcher.EnableRaisingEvents = true;
            OnStatusChangeEventMethod(string.Format("Set filewatcher for directory {0}", directory));
            //if (StatusChange != null) StatusChange(string.Format("Set filewatcher for directory {0}", directory));

            _listOfFileWatcher.Add(filewatcher);

            if (SearchImmediately)
                CheckDirectoryForProcedure(directory, filter, SearchOption.AllDirectories);
        }
        /// <summary>
        /// Change filewatcher directory
        /// </summary>
        /// <param name="DirectoryOld">Old path</param>
        /// <param name="DirectoryNew">New path</param>
        public void ChangeFileWatcher(string DirectoryOld, string DirectoryNew)
        {
            ChangeFileWatcher(DirectoryOld, DirectoryNew, "*.SQL");
        }
        /// <summary>
        /// Change filewatcher directory
        /// </summary>
        /// <param name="DirectoryOld">Old path</param>
        /// <param name="DirectoryNew">New path</param>
        /// <param name="Filter">Filter for watching files</param>
        public void ChangeFileWatcher(string DirectoryOld, string DirectoryNew, string Filter)
        {
            ChangeFileWatcher(DirectoryOld, DirectoryNew, Filter, true, _searchFolderImmediately);
        }
        /// <summary>
        /// Change filewatcher directory
        /// </summary>
        /// <param name="DirectoryOld">Old path</param>
        /// <param name="DirectoryNew">New path</param>
        /// <param name="Filter">Filter for watching files</param>
        /// <param name="IncludeSubdirectories">If include sub directories</param>
        /// <param name="SearchImmediately">If check new folder immediately</param>
        public void ChangeFileWatcher(string DirectoryOld, string DirectoryNew, string Filter, bool IncludeSubdirectories, bool SearchImmediately)
        {
            if (_listOfFileWatcher.Exists(fw => fw.Path == DirectoryOld))
            {
                FileSystemWatcher filewatcher = _listOfFileWatcher.Find(fw => fw.Path == DirectoryOld);
                filewatcher.EnableRaisingEvents = false;
                filewatcher.Path = DirectoryNew;
                filewatcher.Filter = filewatcher.Filter == Filter ? filewatcher.Filter : Filter;
                filewatcher.IncludeSubdirectories = IncludeSubdirectories;
                filewatcher.EnableRaisingEvents = true;
                OnStatusChangeEventMethod(string.Format("Change filewatcher from directory {0} to {1}", DirectoryOld, DirectoryNew));

                if (SearchImmediately)
                    CheckDirectoryForProcedure(DirectoryNew, Filter, SearchOption.AllDirectories);
            }
        }

        public void RemoveFileWather(string directory)
        {
            if (_listOfFileWatcher.Exists(fw => fw.Path == directory))
                _listOfFileWatcher.RemoveAll(fw => fw.Path == directory);
        }

        private void CheckDirectoryForProcedure(string directory, string filter, SearchOption searchOption)
        {
            System.Threading.ThreadPool.QueueUserWorkItem(delegate
                {
                    foreach (string file in Directory.GetFiles(directory, filter, searchOption))
                    {
                        FileInfo e = null;
                        //string procname = string.Empty;
                        try
                        {
                            SetProcDetailsFromFile(file, out e);
                        }
                        catch (Exception ex)
                        {
                            //OnError(e, ex);
                            OnErrorEventMethod(e, ex);
                            //if (ErrorEvent != null) ErrorEvent(e, ex);
                        }
                    }
                });
        }

        private void CheckServerForProcedure(Library.Objects.Server server, Library.Objects.ProcedureInfo procedure)
        {
            System.Threading.ThreadPool.QueueUserWorkItem(delegate
                {
                    foreach (Objects.ProcedureFromDatabase tmpprocedure in Library.Scripts.GetFromSQL.FindTheProcedure(server, procedure))
                    {
                        procedure.SetProcDetailsFromBase(tmpprocedure);
                    }
                });
        }

        private void SetProcDetailsFromFile(FileSystemEventArgs e)//, Procedure.EnumProcType type)
        {

            try
            {
                SetProcDetailsFromFile(new FileInfo(e.FullPath));
            }
            catch (Exception ex)
            {
                OnErrorEventMethod(e, ex);
            }
        }

        private void SetProcDetailsFromFile(FileInfo file)
        {
            SetProcDetailsFromFile(file.FullName, out file);
        }

        private void SetProcDetailsFromFile(string file, out FileInfo e)
        {
            e = null;
            string procname = string.Empty;
            Objects.ProcedureFromFile tmpprocedure = new ProcedureFromFile();
            e = new FileInfo(file);
            OnStatusChangeEventMethod(string.Format("File {0} was found in directory {1}", e.Name, e.Directory));

            procname = e.Name.Remove(e.Name.LastIndexOf('.'));//cut file extension
            tmpprocedure.Location = e.FullName;
            tmpprocedure.ReadFile();
            //TODO prepare for diferent owners and procedure name with "."
            if (procname.StartsWith("dbo.", StringComparison.CurrentCultureIgnoreCase))
            {
                tmpprocedure.Name = procname.Remove(0, procname.IndexOf('.') + 1);
                tmpprocedure.Owner = procname.Remove(procname.IndexOf('.'));
            }
            else
                tmpprocedure.Name = procname;
            lock (_procedureList)
            {
                if (_procedureList.Exists(p => p.Name == tmpprocedure.Name))
                {
                    ((ProcedureInfo)_procedureList.Find(p => p.Name == tmpprocedure.Name)).SetProcDetailsFromFile(tmpprocedure);
                    OnStatusChangeEventMethod(string.Format("Procedure information \"{0}\" in {1} was changed.", tmpprocedure, e.Directory));
                }
            }
        }

        private void FileWatcher_Changed(object sender, FileSystemEventArgs e)
        {
            if (e.ChangeType == WatcherChangeTypes.Changed)
            {
                lock (_filesChanged)
                    if (_filesChanged.ContainsKey(e.FullPath))
                    {
                        if (_filesChanged[e.FullPath] < File.GetLastWriteTime(e.FullPath))
                        {
                            _filesChanged[e.FullPath] = File.GetLastWriteTime(e.FullPath);
                            SetProcDetailsFromFile(e);
                        }
                    }
                    else
                    {
                        _filesChanged.Add(e.FullPath, File.GetLastWriteTime(e.FullPath));
                        SetProcDetailsFromFile(e);
                    }
            }
        }

        private void FileWatcher_Created(object sender, FileSystemEventArgs e)
        {
            if (e.ChangeType == WatcherChangeTypes.Created)
            {
                lock (_filesChanged)
                    if (_filesChanged.ContainsKey(e.FullPath))
                    {
                        if (_filesChanged[e.FullPath] < File.GetLastWriteTime(e.FullPath))
                        {
                            _filesChanged[e.FullPath] = File.GetLastWriteTime(e.FullPath);
                            SetProcDetailsFromFile(e);
                        }
                    }
                    else
                    {
                        _filesChanged.Add(e.FullPath, File.GetLastWriteTime(e.FullPath));
                        SetProcDetailsFromFile(e);
                    }
            }
        }

        private void FileWatcher_Renamed(object sender, RenamedEventArgs e)
        {
            if (e.ChangeType == WatcherChangeTypes.Renamed)
            {
                OnStatusChangeEventMethod(string.Format("File name changed from \"{0}\" to \"{1}\" in path \"{2}\"", e.OldName, e.Name, e.FullPath));
                OnErrorEventMethod(sender, new NotImplementedException());
            }
        }

        /// <summary>
        /// Add new procedure to list ma name
        /// </summary>
        /// <param name="procname">procedure name</param>
        /// <returns>tru if has been added</returns>
        public bool AddProcedure(string procname)
        {
            return AddProcedure(new ProcedureInfo(procname.Trim()));
        }

        /// <summary>
        /// Add new procedure to list
        /// </summary>
        /// <param name="procname">procedure</param>
        /// <returns>tru if has been added</returns>
        public bool AddProcedure(ProcedureInfo procedure)
        {
            if (!_procedureList.Exists(p => p.Name == procedure.Name))
            {
                procedure.ProcedureEnds += new Result.DelegateLookingProcedureEnds(procedure_ProcedureEnds);
                _procedureList.Add(procedure);
                GetDataAboutProcedure(procedure);
                //ProcedureInfo.SetNewVersionAddEvent(procedure_OnNewVersionAdd);
                OnNewProcedureAdded(procedure);
                //procedure.SetProcSzczegFromFile(Library.Objects.ProjectSettings.Instance.ProjectOldProcedureLocation, Library.Objects.ProjectSettings.Instance.ProjectNewProcedureLocation);
                return true;
            }
            else
                return false;
        }

        /// <summary>
        /// Add new procedure range to list
        /// </summary>
        /// <param name="procname">procedure</param>
        /// <returns>tru if has been added</returns>
        public bool AddProcedure(List<Library.Objects.IProcedureInfo> proclist)
        {
            _procedureList.AddRange((List<Library.Objects.IProcedureInfo>)proclist);
            foreach (Objects.ProcedureInfo procedure in proclist)
            {
                return AddProcedure(procedure);
                //procedure.ProcedureEnds +=new Result.DelegateLookingProcedureEnds(procedure_ProcedureEnds);
                ////ProcedureInfo.SetNewVersionAddEvent(procedure_OnNewVersionAdd);
                //OnNewProcedureAdded(procedure);
            }
            return true;
        }

        public bool AddProcedureFromClipboard()
        {
            if (Clipboard.ContainsData("listBox_Procedury.SelectedItems"))
            {
                var deslist = DeSerialize(Clipboard.GetData("listBox_Procedury.SelectedItems").ToString());
                foreach (Library.Objects.IProcedureInfo tmpproc in (List<Library.Objects.IProcedureInfo>)deslist)
                {
                    System.Diagnostics.Debug.WriteLine(tmpproc);
                }
                return Settings.Instance.ProjectSettings.AddProcedure((List<Library.Objects.IProcedureInfo>)deslist);
            }
            else
            {
                string text = Clipboard.GetText();
                //string tmptext = string.Empty;
                char[] seperators = { '\n', '\r', ' ' };
                string[] test = text.Split(seperators, StringSplitOptions.RemoveEmptyEntries);
                string existsProcedures = string.Empty;

                foreach (string tmptext in test)
                {
                    string procstr = tmptext;
                    if (procstr.StartsWith("dbo.", StringComparison.InvariantCultureIgnoreCase)) procstr = procstr.Remove(0, 4);
                    if (procstr.EndsWith(".sql", StringComparison.InvariantCultureIgnoreCase)) procstr = procstr.Remove(procstr.LastIndexOf('.'));
                    if (!string.IsNullOrWhiteSpace(procstr))
                    {
                        if (!Settings.Instance.ProjectSettings.AddProcedure(procstr))
                        {
                            existsProcedures += procstr + "\r\n";
                        }
                        else
                            if (StatusChange != null) StatusChange("Procedure " + procstr + " has been added. " + Library.Objects.ProjectSettings.Instance.ProceduresList.Find(p => p.Name == procstr).Name);
                    }
                }
                if (existsProcedures.Length != 0)
                {
                    MessageBox.Show("Already exists on the list:\r\n" + existsProcedures, "Warning!!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
                return true;
            }
            //((CurrencyManager)listBox_Procedury.BindingContext[listBox_Procedury.DataSource]).Refresh();
        }

        public void CutProcedures(List<Objects.ProcedureInfo> procList)
        {
            try
            {
                string text = string.Empty;
                List<Objects.IProcedureInfo> list = new List<Objects.IProcedureInfo>();

                Clipboard.Clear();
                //ListBox.SelectedObjectCollection tmpList = listBox_Procedury.SelectedItems;
                foreach (Library.Objects.IProcedureInfo tmpprocedure in procList)
                {
                    text += tmpprocedure.Name;
                    text += "\r\n";
                    list.Add(tmpprocedure);
                }

                //TODO collection of temporary remowed object ProcedureResultInformation
                //Clipboard.SetData("SelectedObjectCollection", listBox_Procedury.SelectedItems);

                //foreach (Library.Objects.ProcedureInfo ip in listBox_Procedury.SelectedItems)
                //{
                //    list.Add(ip);
                //}

                Clipboard.SetData("listBox_Procedury.SelectedItems", Serialize(list));//.SetData("SelectedObjectCollection", listBox_Procedury.SelectedItems);


                //var deslist = DeSerialize(Clipboard.GetData("listBox_Procedury.SelectedItems").ToString());
                //Clipboard.SetDataObject(list);

                //Clipboard.SetText(text);


                int a = procList.Count;

                for (int index = 0; index < a; index++)
                {
                    //NewEventDeleteProcedure((Library.Objects.ProcedureInfo)Library.Objects.ProjectSettings.Instance.ProceduresList.Find(p => p == listBox_Procedury.SelectedItems[0]));
                    Library.Objects.ProjectSettings.Instance.RemoweProcedure((Library.Objects.IProcedureInfo)procList[index]);//.Remove(ProjectSettings.ProceduresList.Find(p=>p==listBox_Procedury.SelectedItems[0]));
                    //((CurrencyManager)listBox_Procedury.BindingContext[listBox_Procedury.DataSource]).Refresh();
                    //listBox_Procedury.Items.Remove(listBox_Procedury.SelectedItems[0]);
                }
                //NotSaved();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, ex.Source);
                if (ErrorEvent != null)
                {
                    ErrorEvent(this, ex);
                }
            }
        }

        public void CopyProcedures(IList<Objects.ProcedureInfo> procList)
        {
            StringBuilder strb = new StringBuilder();

            Clipboard.Clear();
            for (int i = 0; i < procList.Count; i++)
            {
                strb.AppendLine(procList[i].ToString());
            }
            //MessageBox.Show(text);
            Clipboard.SetText(strb.ToString());
            //MessageBox.Show(Clipboard.GetText());
        }

        private void procedure_ProcedureEnds(ProcedureInfo procedure)
        {
            if (_queue.Count >= 1)
            {
                IProcedureInfo tmpProcedure = _queue.Dequeue();
                if (this.CheckIfCanStartLookForProcedure((ProcedureInfo)tmpProcedure) && !this.ForceStop)
                {
                    tmpProcedure.Start();
                    //RunnigProcesses++;
                }
            }
        }

        /// <summary>
        /// Add new procedure to list
        /// </summary>
        /// <param name="procname">procedure</param>
        /// <returns>tru if has been added</returns>
        public bool RemoweProcedure(Library.Objects.IProcedureInfo procedure)
        {
            if (_procedureList.Exists(p => p.Name == procedure.Name))
            {
                _procedureList.Remove(procedure);
                NewEventDeleteProcedure(procedure);
                //ProcedureInfo.SetNewVersionAddEvent(procedure_OnNewVersionAdd);
                //GetDataAboutProcedure(procedure);
                //procedure.SetProcSzczegFromFile(Library.Objects.ProjectSettings.Instance.ProjectOldProcedureLocation, Library.Objects.ProjectSettings.Instance.ProjectNewProcedureLocation);
                return true;
            }
            else
                return false;
        }

        /// <summary>
        /// Remowe procedure range to list
        /// </summary>
        /// <param name="procname">procedure</param>
        /// <returns>tru if has been added</returns>
        public bool RemoweProcedure(List<Library.Objects.IProcedureInfo> proclist)
        {
            foreach (Objects.ProcedureInfo procedure in proclist)
            {
                //ProcedureInfo.SetNewVersionAddEvent(procedure_OnNewVersionAdd);
                NewEventDeleteProcedure(procedure);
                _procedureList.RemoveAll(p => p.Equals(procedure));
            }
            return true;
        }

        private bool ProjectSettings_NewEventAddNewProcedure(ProcedureInfo procedure)
        {
            return LocalStorage.AddProcedure(procedure);
        }

        private void procedure_OnNewVersionAdd(object sender, IProcedure proc)
        {
            if (LocalStorage.AddProcedure((IProcedure)proc))
            {
                LocalStorage.SaveFile((IProcedure)proc, new MemoryStream(Encoding.ASCII.GetBytes(proc.Text)));
            }
            else
            {

            }
            //throw new NotImplementedException();
        }

        private void procedure_OnVersionChange(object sender, VersionChangeEventArgs e)
        {
            if (LocalStorage.VersionChange(sender, e))
            {
                LocalStorage.SaveFile((IProcedure)e.New.Parent, new MemoryStream(Encoding.ASCII.GetBytes(e.New.Parent.Text)));
            }
            else
            {

            }
            //throw new NotImplementedException();
        }

        private void procedure_OnProcedureUpdate(object sender, IProcedure proc)
        {
            procedure_OnNewVersionAdd(sender, proc);
            //throw new NotImplementedException();
        }

        public void GetDataAboutProcedure(Library.Objects.ProcedureInfo procedure)
        {
            //List<Objects.Procedure> tmpProcedureInfoList = new List<Objects.Procedure>();
            try
            {
                foreach (Library.Objects.Server server in Library.Objects.ProjectSettings.Instance.Servers)
                {
                    CheckServerForProcedure(server, procedure);
                }
                foreach (ObservedDirectory dir in _observedDirectories)
                {
                    CheckDirectoryForProcedure(dir.Directory, string.Format("*{0}*.sql", procedure.Name), SearchOption.AllDirectories);
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Warning!!");
                OnErrorEventMethod(this, ex);
            }
            //return tmpProcedureInfoList;
        }

        internal Table FindObjectByPath(string name, string p, Type type)
        {
            switch (type.FullName)
            {
                case "Nizm0.QOT.Library.Objects.Table":
                    {
                        string[] strtab = p.Split('.');
                        if (this.Servers.Exists(s => s.Address == strtab[0]))
                        {
                            Server tmpserver = this.Servers.Find(s => s.Address == strtab[0]);
                            if (tmpserver.DataBase.Exists(d => d.Name == strtab[1]))
                            {
                                DataBase tmpDataBase = tmpserver.DataBase.Find(d => d.Name == strtab[1]);
                                if (tmpDataBase.Tables.Exists(t => t.Name == name))
                                {
                                    return tmpDataBase.Tables.Find(t => t.Name == name);
                                }
                                else
                                    return null;
                            }
                            else
                                return null;
                        }
                        else
                            return null;
                    }
                default:
                    return null;
            }
        }

        /// <summary>
        /// Serialize object to binary
        /// </summary>
        /// <param name="objectToSerialize"></param>
        /// <returns></returns>
        private string Serialize(object objectToSerialize)
        {
            string serialString = null;
            using (System.IO.MemoryStream ms1 = new System.IO.MemoryStream())
            {
                BinaryFormatter b = new BinaryFormatter();
                b.Serialize(ms1, objectToSerialize);
                byte[] arrayByte = ms1.ToArray();
                serialString = Convert.ToBase64String(arrayByte);
            }
            return serialString;
        }

        /// <summary>
        /// Deserialize binary string to object
        /// </summary>
        /// <param name="serializationString"></param>
        /// <returns></returns>
        private object DeSerialize(string serializationString)
        {
            object deserialObject = null;
            byte[] arrayByte = Convert.FromBase64String(serializationString);
            using (System.IO.MemoryStream ms1 = new System.IO.MemoryStream(arrayByte))
            {
                BinaryFormatter b = new BinaryFormatter();
                deserialObject = b.Deserialize(ms1);
            }
            return deserialObject;
        }

        #endregion

        private void OnNewProcedureAdded(ProcedureInfo procedure)
        {
            if (NewEventAddNewProcedure != null)
                NewEventAddNewProcedure(procedure);
        }
        private void OnErrorEventMethod(object sender, Exception ex)
        {
            if (ErrorEvent != null) ErrorEvent(sender, ex);
        }
        private void OnStatusChangeEventMethod(string str)
        {
            if (StatusChange != null) StatusChange(str);
        }

        //public void OpenProcedure(object sender, Library.OpenFormEventArgs e)
        //{
        //    OnOpenProcedure(sender, e);
        //}

        public void OnOpenProcedure(object sender, Library.OpenFormEventArgs e)
        {
            if (OpenProcedure != null)
                OpenProcedure(sender, e);
        }

        public XmlSchema GetSchema()
        {
            throw new NotImplementedException();
        }

        //private const string caseProcedureType = typeof(Procedure).FullName;
        public void ReadXml(XmlReader reader)
        {
            reader.MoveToContent();

            this._projectName = reader.GetAttribute("Name");
            Int32.TryParse(reader.GetAttribute("Queries"), out this._queries);


            XmlDocument xmldoc = new XmlDocument();
            xmldoc.Load(reader);
            foreach (XmlNode rootNode in xmldoc.ChildNodes)
                foreach (XmlNode node in rootNode.ChildNodes)
                    foreach (XmlNode node2 in node.ChildNodes)
                    {
                        String className = node2.Name.Trim(); //read the class name 
                        //use the namespace IDelivery is located in

                        Type objectType = (from asm in AppDomain.CurrentDomain.GetAssemblies()
                                           from type in asm.GetTypes()
                                           where type.IsClass && type.Name == className
                                           select type).SingleOrDefault();//.Single();

                        //className = "Nizm0.QOT.Library.Objects." + className;
                        //Type classType = Type.GetType(className);

                        XmlReader r = new XmlNodeReader(node2);

                        System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(objectType);//Type.GetType(className));
                        var obj = Convert.ChangeType(serializer.Deserialize(r), objectType);//Type.GetType(className));
                        PinByOjectType(objectType, obj);
                    }
        }

        private void PinByOjectType(Type objectType, object obj)
        {
            switch (objectType.FullName)
            {
                case "Nizm0.QOT.Library.Objects.ProcedureInfo":
                    {
                        _procedureList.Add((Library.Objects.ProcedureInfo)obj);
                        break;
                    }
                case "Nizm0.QOT.Library.Objects.Server":
                    {
                        _servers.Add((Library.Objects.Server)obj);
                        break;
                    }
                case "Nizm0.QOT.Library.Objects.ObservedDirectory":
                    {
                        _observedDirectories.Add((Library.Objects.ObservedDirectory)obj);
                        break;
                    }
                default:
                    {
                        break;
                    }
            }
        }

        public void WriteXml(XmlWriter writer)
        {
            writer.WriteAttributeString("Name", this._projectName);
            writer.WriteAttributeString("Queries", this._queries.ToString());
            writer.WriteStartElement("ObservedDirectories");
            WriteXmlDirectoryList(writer);
            writer.WriteEndElement();

            writer.WriteStartElement("ServerList");
            WriteXmlServerList(writer);
            writer.WriteEndElement();
            writer.WriteStartElement("ProcedureList");
            WriteXmlProcedureList(writer);
            writer.WriteEndElement();
            //writer.WriteStartElement("ProjectList");
            //WriteXmlProjectList(writer);
            //writer.WriteEndElement();
        }

        private void WriteXmlDirectoryList(XmlWriter writer)
        {
            foreach (ObservedDirectory dir in this._observedDirectories)
            {
                var nsSerializer = new XmlSerializerNamespaces();
                nsSerializer.Add("", "");
                System.Xml.Serialization.XmlSerializer xmlSerializer = new System.Xml.Serialization.XmlSerializer(dir.GetType(), "");
                xmlSerializer.Serialize(writer, dir, nsSerializer);
                //writer.WriteStartElement("Directory");
                //writer.WriteAttributeString("Dir", dir);
                //writer.WriteEndElement();
            }
        }

        private void WriteXmlServerList(XmlWriter writer)
        {
            foreach (Library.Objects.Server serv in _servers)
            {
                if (serv.UseInThisProject)
                {
                    var nsSerializer = new XmlSerializerNamespaces();
                    nsSerializer.Add("", "");
                    System.Xml.Serialization.XmlSerializer xmlSerializer = new System.Xml.Serialization.XmlSerializer(serv.GetType(), "");
                    xmlSerializer.Serialize(writer, serv, nsSerializer);
                }
            }
        }

        private void WriteXmlProcedureList(XmlWriter writer)
        {
            foreach (Library.Objects.IProcedureInfo proc in _procedureList)
            {
                var nsSerializer = new XmlSerializerNamespaces();
                nsSerializer.Add("", "");
                System.Xml.Serialization.XmlSerializer xmlSerializer = new System.Xml.Serialization.XmlSerializer(proc.GetType(), "");
                xmlSerializer.Serialize(writer, proc, nsSerializer);
            }
        }
    }
}
